Q: I'm trying to programatically eject the
floppy disk on which my application resides. I need to keep my
application running while I programatically access another diskette,
a process is similar to an installer. (That's how I know it can be
done.) How do I avoid the "Please insert 'Name of Floppy Disk' " alert
and keep my application running?
A: The problem is relatively simple to
describe. If a program accesses an open file on an ejected volume,
the system asks the user to insert the disk on which the volume
resides. You can, of course, avoid making File Manager calls which
read the disk. But resources are a different story.
The Mac OS application programming model assumes the availability
of a resource file associated with the application. While your app is
running, its resource fork is open, and from time to time resources
are read from that file into memory. These resources may be read in
for a number of reasons, including (but not necessarily limited
to):
- explicit calls to
GetResource in your application code
- 68K code segments which load implicitly because of an
inter-segment subroutine call
- Toolbox calls like
GetNewWindow , which take an explicit
parameter identifying the ID of a resource to be read
- Toolbox calls like
StandardOpenDialog , which take no explicit
parameters identifying a resource, but do indeed read resources
from the current application's resource file
- many, many Toolbox calls which implicitly need to read
unspecified resources from the System file and other files in the
System Folder (this is only relevant if the volume on which your
program resides is also the boot volume, which is uncommon
today)
Unfortunately, it's not possible to overcome this design
assumption in any straightforward way. There's no call you can make
that tells the system "Stop loading resources for a while now,
please." Even if there were, much of the rest of the Toolbox would
stop working. |
If you don't need to eject the boot volume, then you could index,
load, and mark unpurgeable every resource in your application
resource fork before ejecting the volume on which your application
resides, but this might require a prohibitive amount of memory. |
A more optimized technique might be to identify which resources
are loaded by your application and, before ejecting the volume, make
sure those resources are loaded (and not purgeable). Maintaining this
list of resources may require a prohibitive amount of tedium: You may
need to do a fair amount of debugger work, probably involving setting
A-trap and TVector breaks on calls which cause resources to be read
from the disk, such as GetResource , LoadResource ,
ReadPartialResource , etc. Also, the list of resources which must be
loaded may well change quite often as your code evolves. |
Unfortunately, there are some portions of the Toolbox which are
very tricky to support in this kind of program. There are a few
Toolbox calls which implicitly purge or detach resources. For
example, disposing a pop-up menu control on certain versions of the
system will release the MENU resource. If the user can re-open a
window which contains such a control, this presents a problem,
because the diskette has already been ejected, and there is no place
from which to load the MENU resource data. Your options here are
limited: you can avoid the problem Toolbox call entirely or find
another way (write your own code) to achieve the same effect. There
is no list of Toolbox calls that have this behavior, and the
behavior will vary on a case-by-case basis. |
If you need to eject the boot volume, your task will be quite
daunting, and will not yield results which will work into the
indefinite future, since the implementation of Toolbox calls can
change, and the resources they must load implicitly can likewise
change. There is no list of resources you must load, and there is no
programmatic way to determine which resources are used by which
Toolbox call. Here's a testimonial from Apple's Installer Tech Lead
about his team's experience dealing with this aspect of the
problem: |
Generally, each new release of system software requires
additional resources to be pre-loaded from the System file.
Every time we see a new disk swap dialog, we use MacsBug to
step back through the call chain until we find the culprit.
This is why we always store the list of System resources to
pre-load in a resource in the application instead of
hard-coding it. If I were a third-party developer, I'd
probably store the list in a separate file to make it easier
to update.
|
Another complicating factor is system extensions, including but
not limited to virus protection software. Some of these extensions
need to get information about the current application in ways which
cause disk access. This is one of the reasons why some installers
warn the user to boot with extensions disabled (hold the shift key
down during boot) before performing an installation.
The bottom line here is that the system's programming model is in
direct conflict with what you are trying to do. We'd like to be able
to provide a simple way to compensate, but this is a deeply-ingrained
design limitation we cannot lift in the forseeable future. What you
are trying to do is not impossible, but it's going to be a lot of
work.
|
[Jul 06 1998]
|